package com.myjar.excel.v2;

import com.myjar.excel.ExcelType;
import com.myjar.excel.annotation.ExcelEntity;
import com.myjar.excel.annotation.ExcelField;
import com.myjar.excel.serializer.ObjectSerializer;
import com.myjar.excel.serializer.SerializerConfig;
import com.myjar.excel.util.IdentityHashMap;
import com.myjar.excel.util.UnsupportedSerializeType;
import lombok.Data;
import org.joor.Reflect;

import java.lang.reflect.Field;
import java.util.Collection;

@Data
public class BeanInfo {

    private Class<?> clazz;
    private ExcelType type;
    private String sheetName;

    private String[] names;
    private int[] orders;
    private ObjectSerializer[] objectSerializers;
    private Field[] fields;

    private final static IdentityHashMap<Class<?>, BeanInfo> cache = new IdentityHashMap<>();

    public static BeanInfo create(Class<?> clazz) throws Exception {
        BeanInfo beanInfo = cache.get(clazz);
        if (beanInfo == null) {
            beanInfo = new BeanInfo(clazz);
            cache.put(clazz, beanInfo);
        }
        return beanInfo;
    }

    public BeanInfo(Class<?> clazz) throws Exception {
        this.clazz = clazz;
        ExcelEntity excelEntity = clazz.getAnnotation(ExcelEntity.class);
        if (excelEntity == null) {
            throw new UnsupportedSerializeType("缺少注解");
        }

        this.type = excelEntity.value();
        this.sheetName = excelEntity.sheetName();

        BeanParser parser = new SortedBeanParser();
        Collection<Field> fields = parser.parse(clazz);
        int size = 0;
        if (fields == null || (size = fields.size()) == 0) {
            throw new ExcelException("缺少需要序列化的字段");
        }

        names = new String[size];
        objectSerializers = new ObjectSerializer[size];
        orders = new int[size];
        this.fields = new Field[size];

        int i = 0;
        for (Field field : fields) {
            ExcelField excelField = field.getAnnotation(ExcelField.class);
            names[i] = excelField.name();
            Class<? extends ObjectSerializer> obj = excelField.serializer();

            objectSerializers[i] = obj == ObjectSerializer.class ?
                    SerializerConfig.get(field.getType()) :
                    obj.newInstance();
            orders[i] = excelField.order();
            this.fields[i] = field;
            i++;
        }
    }
}
